package com.aaa.mbs.service.impl;

import com.aaa.common.bo.CouponHistory;
import com.aaa.common.constants.BusinessConstant;
import com.aaa.common.constants.ExceptionConstant;
import com.aaa.common.constants.ReturnStatus;
import com.aaa.common.util.CustomException;
import com.aaa.common.util.Result;
import com.aaa.common.vo.MemberPassword;
import com.aaa.mbs.dao.MemberDao;
import com.aaa.mbs.entity.Member;
import com.aaa.mbs.property.SendSMProperties;
import com.aaa.mbs.service.MemberService;
import com.aaa.mbs.service.RemoteCouponHistoryService;
import com.aaa.mbs.util.SmsUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.crypto.hash.Sha512Hash;
import org.apache.xmlbeans.impl.jam.mutable.MMember;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * (Member)表服务实现类
 *
 * @author makejava
 * @since 2020-12-04 15:21:09
 */
@Service("memberService")
public class MemberServiceImpl implements MemberService {
    @Resource
    private MemberDao memberDao;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RemoteCouponHistoryService couponHistoryService;

    @Autowired
    private SendSMProperties sendSMProperties;


    @Override
    public Result changePassword(MemberPassword memberPassword) {
        //根据ID获取对象
        Member member = this.queryById(memberPassword.getMemberId());
        //使用原密码再次加密
        Sha512Hash sha512Hash  =new Sha512Hash(memberPassword.getOldPassword(),member.getPwSalt(),1024);
        //判断老密码是否正确
        if(!member.getPassword().equals(sha512Hash.toString())){
            return new Result(ReturnStatus.FAIL.getReturnCode(),
                    ReturnStatus.FAIL.getReturnMsg(), "原密码错误");
        }
        //随机盐值
        String passWordSalt = UUID.randomUUID().toString().substring(0,10);
        //使用新密码再次加密
        Sha512Hash newPassword  =new Sha512Hash(memberPassword.getNewPassword(),passWordSalt,1024);
        //修改验证和密码
        member.setPwSalt(passWordSalt);
        member.setPassword(newPassword.toString());
        //修改密码
        memberDao.update(member);
        return new Result(ReturnStatus.SUCCESS.getReturnCode(),
                ReturnStatus.SUCCESS.getReturnMsg(), "密码修改成功");
    }


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Member queryById(Integer id) {
       return this.memberDao.queryById(id);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param pageNo 查询起始位置
     * @param pageSize 查询条数
     * @param member   实例对象
     * @return 对象列表
     */
    @Override
    public Result queryAllByParam(int pageNo, int pageSize, Member member) {
        if (pageNo == 0 || pageSize == 0){
            throw new CustomException(ExceptionConstant.INVALID_ARGUMENT.getErrorCode(),
                    ExceptionConstant.INVALID_ARGUMENT.getErrorMessage());
        }
        PageHelper.startPage(pageNo,pageSize);
        PageInfo<Member> pageInfo = new PageInfo<>(memberDao.queryAll(member));
        return new Result(ReturnStatus.SUCCESS.getReturnCode(),
                ReturnStatus.SUCCESS.getReturnMsg(), pageInfo);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<Member> queryAllByLimit(int offset, int limit) {
        return this.memberDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     * @param member
     * @return
     */
    @Override
    @Transactional
    public Member insert(Member member) {
        String passWord = member.getPassword();
        String passWordSalt = UUID.randomUUID().toString().substring(0,10);
        Sha512Hash sha512Hash  =new Sha512Hash(passWord,passWordSalt,1024);
        member.setPassword(sha512Hash.toString());
        member.setPwSalt(passWordSalt);
        member.setStatus(0);
        member.setAccountBalance(0);
        member.setIntegration(0);
        member.setMemberLevelId(1);
        member.setHistoryIntegration(0);
        //会员添加
        this.memberDao.insert(member);
        //新用户优惠券赠送
        CouponHistory couponHistory = new CouponHistory();
        //固定200元优惠券-新用户注册 id为1
        couponHistory.setCouponId(1L);
        // couponHistory.setUseTime(); 必须为空
        couponHistory.setMemberId(Long.valueOf(member.getId()));
        couponHistory.setCouponCode("100001");
        couponHistory.setGetType(BusinessConstant.CouponGeTtYPE.HTZS);
        couponHistory.setCreateTime(new Date());
        couponHistory.setUseStatus(1);
        couponHistoryService.insert(couponHistory);
        return member;
    }


    @Override
    public Result updateFront(Member member) {
        if (member.getId() != null) {
            this.memberDao.update(member);
            return new Result(ReturnStatus.SUCCESS.getReturnCode(),
                    ReturnStatus.SUCCESS.getReturnMsg(), this.queryById(member.getId()));
        }
        return null;
    }

    /**
     * 修改数据
     *
     * @param member 实例对象
     * @return 实例对象
     */
    @Override
    public Result update(Member member) {
        //判断参数对象中是否有用户ID
        if (member.getId() != null) {
            this.memberDao.update(member);
            return new Result(ReturnStatus.SUCCESS.getReturnCode(),
                    ReturnStatus.SUCCESS.getReturnMsg(), this.queryById(member.getId()));
        }
        //获取redis中存放的验证码
        String verifyCode = (String) redisTemplate.opsForValue().get(member.getPhoneNum());
        //判断验证码是否正确
        if (verifyCode.equals(member.getToken())) {
            //获取该手机号对应的用户信息
            Member member1 = new Member();
            member1.setPhoneNum(member.getPhoneNum());
            List<Member> memberData = memberDao.queryAll(member1);
            if (memberData.size() > 0) {
                //保存该用户ID
                member.setId(memberData.get(0).getId());
                //随机盐值
                String salt = UUID.randomUUID().toString().substring(0, 15);
                //        System.out.println("随机盐值"+salt);
                //保存随机盐值
                member.setPwSalt(salt);
                //获取用户密码
                String password = member.getPassword();
                //使用SHA512加密算法，把原始密码和随机到的盐值一起进行运算，得到密码，存入数据
                //Sha512Hash(Object source, Object salt, int hashIterations)
                //          第1个参数，原始密码，第2参数，随机盐值  第3参数 hash次数
                //           和配置类中配置的加密算法名称和hash次数一致 com.aaa.sbms.config.ShiroConfig
                Sha512Hash sha512Hash = new Sha512Hash(password, salt, 1024);
                //保存加密后密码
                member.setPassword(sha512Hash.toString());
                this.memberDao.update(member);
                return new Result(ReturnStatus.SUCCESS.getReturnCode(),
                        ReturnStatus.SUCCESS.getReturnMsg(), this.queryById(memberData.get(0).getId()));
            }
            return new Result(ReturnStatus.FAIL.getReturnCode(),
                    ReturnStatus.FAIL.getReturnMsg(), "该手机号不存在");
        }
        return new Result(ReturnStatus.FAIL.getReturnCode(),
                ReturnStatus.FAIL.getReturnMsg(), "验证码错误");
    }

    /**
     * 修改密码
     * @param member
     * @return
     */
    @Override
    public Result updatePwd(Member member) {
        //获取该手机号对应的用户信息
        Member member1 = new Member();
        member1.setPhoneNum(member.getPhoneNum());
        List<Member> memberData = memberDao.queryAll(member1);
        if (memberData.size() > 0) {
            //保存该用户ID
            member.setId(memberData.get(0).getId());
            //将旧密码加密
            Sha512Hash hash = new Sha512Hash(member.getToken(), memberData.get(0).getPwSalt(), 1024);
            //判断旧密码是否正确
            if (hash.toString().equals(memberData.get(0).getPassword())) {
                //随机盐值
                String salt = UUID.randomUUID().toString().substring(0, 15);
//        System.out.println("随机盐值"+salt);
                //保存随机盐值
                member.setPwSalt(salt);
                //获取用户新密码
                String password = member.getPassword();
                //使用SHA512加密算法，把原始密码和随机到的盐值一起进行运算，得到密码，存入数据
                //Sha512Hash(Object source, Object salt, int hashIterations)
                //          第1个参数，原始密码，第2参数，随机盐值  第3参数 hash次数
                //           和配置类中配置的加密算法名称和hash次数一致 com.aaa.sbms.config.ShiroConfig
                Sha512Hash sha512Hash = new Sha512Hash(password, salt, 1024);
                //保存加密后密码
                member.setPassword(sha512Hash.toString());
                this.memberDao.update(member);
                return new Result(ReturnStatus.SUCCESS.getReturnCode(),
                        ReturnStatus.SUCCESS.getReturnMsg(), this.queryById(memberData.get(0).getId()));
            }
            return new Result(ReturnStatus.FAIL.getReturnCode(),
                    ReturnStatus.FAIL.getReturnMsg(), "旧密码不正确");
        }
        return new Result(ReturnStatus.FAIL.getReturnCode(),
                ReturnStatus.FAIL.getReturnMsg(), "该手机号不存在");
    }
    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public Result deleteById(Integer id) {
        if (id == null) {
            throw new CustomException(ExceptionConstant.ID_NOT_NULL.getErrorCode(),
                    ExceptionConstant.ID_NOT_NULL.getErrorMessage());
        }
        return new Result(ReturnStatus.SUCCESS.getReturnCode(),
                ReturnStatus.SUCCESS.getReturnMsg(),
                this.memberDao.deleteById(id)>0);
    }

    @Override
    public Member queryByUserName(String userName) {
        Member paramMember = new Member();
        paramMember.setPhoneNum(userName);
        paramMember.setStatus(0);
        List<Member> members = memberDao.queryAll(paramMember);
        if (members!=null&&members.size()>0){
            return members.get(0);
        }
        return null;
    }

    @Override
    public Result queryMemberByParam(String userNameOrPhoneNum) {
        Member member = memberDao.queryMemberByParam(userNameOrPhoneNum);
        if (member != null){
            return new Result(ReturnStatus.SUCCESS.getReturnCode(),
                    ReturnStatus.SUCCESS.getReturnMsg(),member);
        }else {
            return new Result(ReturnStatus.FAIL.getReturnCode(),
                    ReturnStatus.FAIL.getReturnMsg(),null);
        }
    }


    @Override
    public List<Member> listMember() {
        return memberDao.listMember();
    }



    @Override
    public int insertBy(Member member) {
        return memberDao.insertBy(member);
    }

    @Override
    public Integer forgetPwd(Member member) {
        //获取该手机号对应的用户信息
        Member member1 = new Member();
        member1.setPhoneNum(member.getPhoneNum());
        List<Member> memberData = memberDao.queryAll(member1);
//        System.out.println();
        if (memberData.size() > 0) {
            member.setId(memberData.get(0).getId());
            //随机盐值
            String salt = UUID.randomUUID().toString().substring(0, 15);
            member.setPwSalt(salt);
            //获取用户新密码
            String password = member.getPassword();
            Sha512Hash sha512Hash = new Sha512Hash(password, salt, 1024);
            //保存加密后密码
            member.setPassword(sha512Hash.toString());
//            System.out.println(member);
            return this.memberDao.update(member);
//            }
//            return new Result(ReturnStatus.FAIL.getReturnCode(),
//                    ReturnStatus.FAIL.getReturnMsg(), "旧密码不正确");
        }
        return -1;
    }


    @Override
    public String sendSM(String  phoneNum){
//        System.out.println(phoneNum);
//        Random random = new Random();
        //随机六位数  random.nextInt(100000) 0-99999
        String verifyCode =  String.valueOf(new Random().nextInt(899999) + 100000);
        // String verifyCode = (random.nextInt(100000)+100000)+"";
        //存储验证到redis中 有效值5分钟
        redisTemplate.opsForValue().set(phoneNum, verifyCode,5,TimeUnit.MINUTES);
        return  new SmsUtil().sendSM(sendSMProperties,phoneNum,verifyCode);
    }



}